/*
package com.lazy.utils.exception;


import com.lazy.utils.mail.MailSentService;
import com.lazy.utils.utils.DateTimeUtil;
import com.lazy.utils.utils.IPUtil;
import com.lazy.utils.utils.MD5Util;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisCluster;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Date;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

*/
/**
 * 系统未知异常预警
 * @author zk
 * @since 2018-05-23 10:57
 *//*

@Component
public class UnknownExceptionAlerter {

    @Autowired
    private MailSentService mailSentService;

    @Value("${runtime.sendAlertMail}")
    private boolean sendAlertMail = false;

    @Value("${unkownException.sendMails}")
    private String sendMails = "";

    @Value("${system.id}")
    private String systemId = "unknown";

    @Value("${runtime.environment}")
    private String env = "";

    @Autowired
    private JedisCluster jedisCluster;

    //防止邮箱被撑爆，限制一分钟内单IP最多发送20封报警邮件，超过了则禁用30分钟
    */
/**
     * 一分钟内发送的报警邮件总是
     *//*

    private AtomicInteger sendCount = new AtomicInteger(0);
    */
/**
     * 是否允许发送报警邮件
     *//*

    private AtomicBoolean allowSend = new AtomicBoolean(true);

    private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

    public UnknownExceptionAlerter() {
        // 一分钟清空一次sendCount
        scheduledExecutorService.scheduleAtFixedRate(() -> sendCount.set(0), 1, 1, TimeUnit.MINUTES);

        // 30分钟重置一次allowSend
        scheduledExecutorService.scheduleAtFixedRate(() -> allowSend.set(true), 30, 30, TimeUnit.MINUTES);
    }

    public void sendEmail(Throwable ex, HttpServletRequest request) {
        this.sendEmail(sendMails, ex, request);
    }

    public void sendEmail(String message, HttpServletRequest request) {
        this.sendEmail(sendMails, message, request);
    }

    */
/**
     * 发送报警邮件
     *//*

    public void sendEmail(String mailAddresses, Throwable ex, HttpServletRequest request) {
        String exString = exceptionToString(ex);
        this.sendEmail(mailAddresses, exString, request);
    }

    */
/**
     * 发送报警邮件
     *//*

    public void sendEmail(String mailAddresses, String message, HttpServletRequest request) {
        sendEmail(mailAddresses, message, null, request);
    }

    */
/**
     * 发送报警邮件
     *
     * @param request 请求，可空
     *//*

    public void sendEmail(String mailAddresses, String message, String title, HttpServletRequest request) {
        if (!sendAlertMail) {
            return;
        }
        String exString = message;
        if (filterException(exString)) {
            return;
        }
        String md5Src = exString;
        if (md5Src.contains("com.alibaba.dubbo.remoting.TimeoutException")) {
            md5Src = "com.alibaba.dubbo.remoting.TimeoutException";
        }
        String md5 = MD5Util.MD5(md5Src);
        String key1 = "sendExceptionMail:" + md5;
        String key2 = "30Minite:" + md5;

        // 3小时内错误计数
        long count = jedisCluster.incrBy(key1, 1);
        if (count == 1) {
            jedisCluster.expire(key1, 10800);
        }

        // 半小时只发一次邮件
        long count2 = jedisCluster.incrBy(key2, 1);
        if (count2 == 1) {
            jedisCluster.expire(key2, 1800);
        }
        if (count2 != 1) {
            return;
        }

        //防止邮箱被撑爆，限制一分钟内单IP最多发送20封报警邮件，超过了则禁用30分钟
        if (!allowSend.get()) {
            return;
        }
        int num = sendCount.incrementAndGet();
        // 发送报警邮件已经超过20封了
        if (num > 20) {
            if (num == 21) {
                allowSend.set(false);
                mailSentService.sendMail(mailAddresses, "报警邮件发送频率太高", IPUtil.getLocalIpAddr() + "在1分钟内发送的报警邮件超过20封了，为了防止邮箱被撑爆，禁止发送报警邮件30分钟。");
            }
            return;
        }

        // 发送报警邮件
        StringBuilder content = new StringBuilder();
        content.append("最近3小时内同样错误发生了：").append(count ).append("次");
        content.append("\nMD5：").append(md5);
        content.append("\nSystem：").append(systemId);
        content.append("\nClientIP：");
        content.append(IPUtil.getIpAddr(request));
        content.append("\nServerIP：");
        content.append(IPUtil.getLocalIpAddr());
        content.append("\nSeqId：").append(MDC.get("SeqId"));
        content.append("\n发生时间：").append(DateTimeUtil.toDateTimeStr(new Date()));
        content.append("\n异常摘要：");
        content.append(exString);
        if (title == null) {
            title = systemId + "(" + env + ")系统未知异常";
        } else {
            title = title + "(" + env + ")";
        }
        mailSentService.sendMail(mailAddresses, title, content.toString());
    }

    private String exceptionToString(Throwable t) {
        StringBuilder result = new StringBuilder();
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(baos, true, "UTF-8");
            if (t.getCause() != null) {
                // 如果有原因
                t.getCause().printStackTrace(ps);
                // 如果没有原因
                t.printStackTrace(ps);
                result.append(baos.toString("UTF-8"));
            } else {
                // 如果没有原因
                t.printStackTrace(ps);
                result.append(baos.toString("UTF-8"));
            }
            if (ps != null) {
                ps.close();
            }
            if (baos != null) {
                baos.close();
            }
        } catch (Exception e) {
        }
        return result.toString();
    }

    private boolean filterException(String exString) {
        if (exString.contains("java.io.IOException: Broken pipe")) {
            return true;
        }
        if (exString.contains("Connection reset by peer")) {
            return true;
        }
        if (exString.contains("com.alibaba.dubbo.rpc.RpcException: Forbid consumer")) {
            return true;
        }
        if (exString.contains("org.springframework.web.method.annotation.ModelFactory.findSessionAttributeArguments")) {
            return true;
        }

        return false;
    }

    */
/**
     * @param mailAddresses
     * @param message
     * @param timeout
     * @param maxCount
     * @param request
     * @author wangqiliang
     * 发送报警邮件 指定缓存时间，在缓存时间内发生的次数 发邮件
     *//*

    @SuppressWarnings("unchecked")
    public void sendEmail(String mailAddresses, String message, int timeout, long maxCount, HttpServletRequest request) {
        if (!sendAlertMail) {
            return;
        }

        String md5Src = message;

        String md5 = MD5Util.MD5(md5Src);
        String key = "sendExceptionMail:" + md5;

        //每次发生错误都更新缓存加 1
        long count = jedisCluster.incrBy(key, 1);
        //发生第一次时,设定超时时间单位分钟
        if (count == 1) {
            jedisCluster.expire(key, timeout);
        }
        //发邮件 等于最大统计次数就发邮件
        if (count == maxCount) {
            StringBuilder content = new StringBuilder();
            content.append("最近 ").append(timeout).append(" 分钟内同样问题发生了：").append(count).append("次");
            content.append("\nMD5：").append(md5);
            content.append("\nSystem：").append(systemId);
            content.append("\nClientIP：");
            content.append(IPUtil.getIpAddr(request));
            content.append("\nServerIP：");
            content.append(IPUtil.getLocalIpAddr());
            content.append("\nSeqId：").append(MDC.get("SeqId"));
            content.append("\n发生时间：").append(DateTimeUtil.toDateTimeStr(new Date()));
            content.append("\n异常摘要：");
            content.append(message);
            mailSentService.sendMail(mailAddresses, systemId + "(" + env + ")系统未知异常", content.toString());
        }
    }
}
*/
